home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
pctj0487.arc
/
CE_TEST.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-02-17
|
15KB
|
407 lines
;====================================================================
; CE_TEST Dan Rollins December 15, 1986
; This program illustrates techniques for intercepting and replacing
; the DOS Critical Error handler. It shows how to:
; * save and restore the application screen
; * make the error message popup in a window
; * allow the error handler to return directly to the application
; program, passing back a DOS error code (even for DOS 2.x).
;
; After installing an INT 24H handler, it attempts to open a file on
; drive A, then attempts to send characters to the printer.
;
; This is a COM-format program and must be processed with EXE2BIN
;=====================================================================
; MACROS used in this listing
;=====================================================================
$set_csr macro line,clm ;;this positions the cursor
mov dx,((line)*256)+clm
mov ah,2
mov bh,0
int 10H
endm
$disp macro string ;;this displays a string
ifnb <string>
mov dx,offset string ;;if string given, point DX to it
endif ;; otherwise, assume DX is set
call disp_msg
endm
;=====================================================================
; Code and data to install and test the error handler. This is
; the "application program" that is disrupted by a critical error.
;=====================================================================
code_seg segment
assume cs:code_seg, ds:code_seg, es:code_seg
org 100H ;must have for COM-format programs
ce_test proc near
jmp start
filespec db "a:\erase.me",0 ;filespec used in disk test
test_msg db "This is a test message ",0dh,0ah ;for printer test
MSG_LEN equ ($-test_msg)
prtr_msg db "Printer error test. Press a key...",0
disk_msg db "Disk A: error test. Press a key...",0
new_line db 0dh,0ah,0
no_err_msg db "Returned from DOS function without error.",0dh,0ah,0
ret_err_msg db "Error "
ret_code dw ? ;this is filled with 2 ASCII digits
db " upon return from DOS function.",0ah,0dh,0
start: mov al,24H ;DOS critical error interrupt number
mov ah,25H ;function to replace an int vector
mov dx,offset crit_err
int 21H ;local error handler is in place
$disp disk_msg ;display a message and await a key
call get_key
$disp new_line
;------ disk test just attempts to open a file on drive A
mov dx,offset filespec
mov cx,0 ;normal attribute
mov ah,3cH ;create file
int 21H
jnc ct_20 ;if no error, continue
push ax ;else, stabilise DOS
mov ah,19H ; with dummy call to function 19H,
int 21H ; get current drive
pop ax
mov bl,10 ;setup string with error number
div bl
add ax,3030H ;force binary to ASCII
mov ret_code,ax
$disp ret_err_msg ;and display the resulting string
jmp ct_30
ct_20:
$disp no_err_msg
ct_30: ;------ printer test sends text to standard printer device
$disp prtr_msg ;display a message and await a key
call get_key
$disp new_line
mov bx,4 ;handle reserved for standard printer
mov cx,MSG_LEN
mov dx,offset test_msg
mov ah,40H ;DOS write_handle function
int 21H
jnc ct_40 ;if no error, continue
push ax ;else, stabilise DOS
mov ah,19H ; with dummy call to function 19h,
int 21H
pop ax
mov bl,10 ;setup string with error number
div bl
add ax,3030H
mov ret_code,ax
$disp ret_err_msg ; and display it
jmp ct_exit
ct_40:
$disp no_err_msg
ct_exit: mov ah,4cH ;DOS exit function
int 21H
ce_test endp
;=====================================================================
; Start of Critical Error handler code and data
;=====================================================================
WIN_TOP equ 10 ;these equate describe the popup
WIN_LEFT equ 20 ;window used by the error handler
WIN_HIGH equ 4
WIN_WIDE equ 40
WIN_ATTR equ 70H ;reverse video screen attribute
devhdr_addr label dword ;these values are saved upon entry
devhdr_off dw ?
devhdr_seg dw ?
save_ax dw ?
save_di dw ?
save_sp dw ? ;these are used in a CANCEL request
app_err dw ?
response_msg db "Retry or Cancel? (press R or C) ",0
crit_err proc far
mov cs:save_sp,sp ;save the stack position at start
push ax ;save DOS's registers
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
push cs
pop ds
mov devhdr_off,si ;save address of the device header
mov devhdr_seg,bp
mov save_ax,ax ;save err type & read/write bit flags
mov save_di,di ;save error code
and di,00ffH ;get critical error code
add di,19 ;convert to DOS error code
mov app_err,di ;save in case we return directly to
; the interrupted application
call save_scrn
call clr_window
mov ax,save_ax
test ah,80H ;disk error ?
jnz ce_10 ; no, process character device error
call disk_err ; yes, process disk error
jmp ce_20
ce_10: call char_err
ce_20:
$set_csr <WIN_TOP+3>,<WIN_LEFT+1>
$disp response_msg ;display "Retry or Cancel" message
ce_30: call get_key
or al,32 ;force response to lowercase
cmp al,'c' ;request to Cancel?
je ce_50 ; yes, go
cmp al,'r' ;request to Retry?
je ce_40
call beep ;else, invalid response
jmp ce_20 ;go back an wait for a vaild response
ce_40: ;-------------------- action taken on RETRY request
call restore_scrn ;leave screen as it was before error
pop ds ;restore DOS registers
pop es
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
mov al,1 ;set "Retry" return code
iret ;and exit to DOS
ce_50: ;--------------------- action taken on CANCEL request
call restore_scrn ;leave screen as it was before error
mov sp,cs:save_sp ;locally-saved regs are irrelevant
pop ax ;and discard DOS IP
pop ax ; DOS CS
pop ax ; DOS flags
pop ax ;restore application's registers
pop bx
pop cx
pop dx
pop si
pop di
pop bp
pop ds
pop es
push bp ;set the carry flag (on the stack)
mov bp,sp ; so the application will
or word ptr [bp+6],1 ; notice that an error occurred
pop bp
mov ax,cs:app_err ;and pass back a DOS error code
iret
crit_err endp
;=====================================================================
; Start of code and data specific to character device errors
;=====================================================================
gen_msg db "General failure on ",0
paper_msg db "Printer out of paper on ",0
read_msg db "Error reading from ",0
write_msg db "Error writing to ",0
device_msg db "device '"
dev_name db 9 dup(?)
char_err proc near
$set_csr <WIN_TOP+1>,<WIN_LEFT+1>
mov bx,save_di ;fetch the error code
mov dx,offset gen_msg ; assume "general failure" error
cmp bl,9 ; is it a "paper out" error?
jne ch_10 ; no, go.
mov dx,offset paper_msg
ch_10: cmp bl,0aH ; is it a "write fault" error?
jne ch_20 ; no, go.
mov dx,offset write_msg
ch_20: cmp bl,0bH ; is it a "read fault" error?
jne ch_30 ; no, go.
mov dx,offset read_msg
ch_30: $disp
;------- now find the name of the malfunctioning device
push ds
lds si,cs:devhdr_addr
add si,0aH ;point to device name in driver header
push cs
pop es
mov di,offset dev_name ;point to local buffer for name
mov cx,8 ; 8 characters max
ch_40: lodsb ; get a character
cmp al,' ' ;end of device name?
je ch_50 ; yes, go
stosb ; no, add to local string
loop ch_40 ; get next character
ch_50:
pop ds
mov al,"'" ;close quote on the device name: 'PRN'
stosb
mov al,0 ; and make string ASCIIZ
stosb
$disp device_msg
ret
char_err endp
;=====================================================================
; Start of code and data specific to disk errors
;=====================================================================
disk_read_msg db "Disk read ",0
disk_write_msg db "Disk write ",0
disk_err_msg db "error on drive "
disk_id db "A:",0
write_prot_msg db "Disk is write-protected.",0
not_ready_msg db "Drive door may be open.",0
bad_media_msg db "The disk media seems to be flawed.",0
gen_fail_msg db "General failure of the drive.",
disk_msg_tbl dw write_prot_msg, gen_fail_msg, not_ready_msg ;1,2,3
dw gen_fail_msg, bad_media_msg, gen_fail_msg ;4,5,6
dw bad_media_msg, bad_media_msg, bad_media_msg ;7,8,9
dw gen_fail_msg, gen_fail_msg, gen_fail_msg ;a,b,c
dw gen_fail_msg ;d
disk_err proc near
$set_csr <WIN_TOP+1>,<WIN_LEFT+1>
mov ax,save_ax
add al,'A'
mov disk_id,al
mov dx,offset disk_read_msg ;assume read error
test ah,1
jz de_10
mov dx,offset disk_write_msg
de_10: $disp ;display "Disk Write " or "Disk Read "
$disp disk_err_msg ;display "error on drive x:"
$set_csr <WIN_TOP+2>,<WIN_LEFT+1>
mov bx,save_di ;look up which message to display
mov bh,0
shl bx,1 ;each address entry is 2 bytes long
mov dx,disk_msg_tbl[bx]
$disp
ret
disk_err endp
;=====================================================================
; Start of general-purpose and library routines
;=====================================================================
include ce_conio.asm ;insert console I/O routines
;---------------------------------------------------------------------
; CLR_WINDOW
; This function clears the error message window.
; Window position, size, and display attributes are set by equates.
;---------------------------------------------------------------------
clr_window proc near
mov ch,WIN_TOP
mov cl,WIN_LEFT
mov dh,WIN_TOP + WIN_HIGH
mov dl,WIN_LEFT + WIN_WIDE
mov bh,WIN_ATTR
mov al,0 ; AL=0 means clear window
mov ah,6 ;BIOS scroll_window service
int 10H
ret
clr_window endp
;---------------------------------------------------------------------
; SAVE_SCRN
; This function save's the application's screen
; and cursor position. Doesn't work for graphics-mode screens
;---------------------------------------------------------------------
save_scrn proc near
push ds
push es
mov bh,0 ;assume video page 0
mov ah,3
int 10H ;get cursor position
mov cs:save_csr,dx ;save for restore_scrn function
int 11H ;locate video memory segment
mov bx,0b800H ;assume color card
and ax,30H
cmp ax,30H
jne sc_10
mov bx,0b000H ;must be mono card
sc_10:
mov cs:scrn_seg,bx ;save for restore_scrn function
mov ds,bx ;source is video memory
mov si,0
push cs ;destination is local scrn buffer
pop es
mov di,offset scrn_buf
mov cx,2000 ;count of words on entire screen
rep movsw
pop es
pop ds
ret
save_scrn endp
;---------------------------------------------------------------------
; RESTORE_SCRN
; this function restore's the application's screen
; and cursor position
;---------------------------------------------------------------------
restore_scrn proc near
push ds
push es
mov dx,cs:save_csr ;fetch application's cursor pos
mov ah,2
mov bh,0 ;assume video page 0
int 10H ;set cursor position
push cs ;source is local screen storage
pop ds
mov si,offset scrn_buf
mov es,cs:scrn_seg ;destination is video memory
mov di,0
mov cx,2000 ;count of words on entire screen
rep movsw
pop es
pop ds
ret
restore_scrn endp
scrn_seg dw ? ;used by save_scrn and restore_scrn
save_csr dw ?
scrn_buf label word ;local screen storage begins here
code_seg ends
end ce_test